package nl.vu.few.ibivu.biomodels.server;

import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.logging.Logger;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.xml.transform.Result;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMResult;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;

@SuppressWarnings("serial")
public class UniprotProxy extends HttpServlet {
	private static final Logger log = Logger.getLogger(UniprotProxy.class.getName());
	
	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp)
			throws ServletException, IOException {
		// The argument of our query to Uniprot
		String query = req.getParameter("q");
		// If the parameter is set the Uniprot namespace
		// will not be included in the resulting XML
		String removeNs = req.getParameter("r");
		StreamSource xslSource = null;
		StreamSource nsXslSource = null;
		StreamSource xmlSource = null;

		TransformerFactory tFactory = TransformerFactory.newInstance();
		resp.setContentType("text/xml");
		try {
			// Initialize the first transformation
			xslSource = new StreamSource(getServletContext().getResourceAsStream("/xsl/uniprot.xsl"));
			Transformer transformer = tFactory.newTransformer(xslSource);
			
			if (query == null) {
				// If the query is null, instead of quering Uniprot we provide an empty XML as source
				xmlSource = new StreamSource(getServletContext().getResourceAsStream("/xsl/empty.xml"));
			}
			else {
				// Let's query Uniprot
				URL url = new URL("http://www.uniprot.org/uniprot/?query=" + query + "&sort=score&limit=10&format=xml");
				xmlSource = new StreamSource(url.openStream());
			}
			
			Result result = null;
			if (removeNs != null) {
				// If we want to remove the namespace we need a place
				// to store the result of the first transformation..
				result = new DOMResult();
			}
			else {
				// .. Otherwise we can already write our output
				result = new StreamResult(resp.getOutputStream());
			}
			// Complete the first transformation
			transformer.transform(xmlSource, result);

			if (removeNs != null) {
				// If we want to remove the namespace prepare the second transformation
				// with the previously generated result as source
				nsXslSource = new StreamSource(getServletContext().getResourceAsStream("/xsl/removens.xsl"));
				Transformer nsTransformer = tFactory.newTransformer(nsXslSource);
				// Finally transform and write the output
				nsTransformer.transform(new DOMSource(((DOMResult) result).getNode()), new StreamResult(resp.getOutputStream()));
			}
		} catch (MalformedURLException e) {
			log.severe(e.getMessage());
		} catch (IOException e) {
			log.severe(e.getMessage());
		} catch (TransformerConfigurationException e) {
			log.severe(e.getMessage());
		} catch (TransformerException e) {
			// FIXME handle the case in which uniprot can't find any match
			log.severe(e.getMessage());
		} finally {
			try {
				if (nsXslSource != null && nsXslSource.getInputStream() != null)
					nsXslSource.getInputStream().close();
				if (xslSource != null && xslSource.getInputStream() != null)
					xslSource.getInputStream().close();
				if (xmlSource != null && xmlSource.getInputStream() != null)
					xmlSource.getInputStream().close();
			} catch (IOException ex) {
			}
		}
	}

}
